package com.decent.manager.system.auth.content;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.decent.common.constant.Constants;
import com.decent.common.entity.manager.SystemUser;
import com.decent.common.enums.AuthExceptionEnum;
import com.decent.common.enums.ErrorCodeEnum;
import com.decent.common.enums.manager.UserTypeEnum;
import com.decent.common.exception.ErrorCodeException;
import com.decent.manager.system.auth.service.AuthService;
import com.decent.manager.system.auth.vo.LoginData;
import com.decent.manager.system.auth.vo.LoginUser;
import com.decent.manager.config.security.context.LoginContext;
import com.decent.manager.system.dao.SystemUserDao;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @className: SpringSecurityLoginContextImpl
 * @author: wangyan
 * @date: 2022/4/16
 **/
@Service
public class SpringSecurityLoginContextImpl implements LoginContext {
    @Resource
    private AuthService authService;
    @Resource
    private SystemUserDao systemUserDao;

    /**
     * 获取当前登录用户
     */
    @Override
    public LoginUser getLoginUser() {
        Authentication authentication = authService.getAuthentication();
        if (ObjectUtil.isEmpty(authentication) || authentication.getPrincipal() instanceof String) {
            throw new ErrorCodeException(ErrorCodeEnum.NO, AuthExceptionEnum.NO_LOGIN_USER.getMessage());
        } else {
            return (LoginUser) authentication.getPrincipal();
        }
    }

    /**
     * 获取当前登录用户，如未登录，则返回null，不抛异常
     */
    @Override
    public LoginUser getLoginUserWithoutException() {
        Authentication authentication = authService.getAuthentication();
        if (ObjectUtil.isEmpty(authentication) || authentication.getPrincipal() instanceof String) {
            return null;
        } else {
            return (LoginUser) authentication.getPrincipal();
        }
    }

    /**
     * 获取当前登录用户的id
     */
    @Override
    public Long getLoginUserId() {
        return this.getLoginUser().getId();
    }

    /**
     * 获取当前登录用户的名
     *
     * @return 当前登录用户的name
     */
    @Override
    public String getLoginUserName() {
        return this.getLoginUser().getUserName();
    }

    /**
     * 获取当前登录的用户账号
     */
    @Override
    public String getLoginUserAccount() {
        return this.getLoginUser().getUserAccount();
    }

    /**
     * 判断当前登录用户是否有某资源的访问权限
     */
    @Override
    public boolean hasPermission(String requestUri) {
        String removePrefix = StrUtil.removePrefix(requestUri, Constants.LEFT_DIVIDE);
        String requestPermission = removePrefix.replaceAll(Constants.LEFT_DIVIDE, Constants.COLON);
        return this.getLoginUser().getPermissions().contains(requestPermission);
    }

    /**
     * 判断当前登录用户是否包含任意一个角色
     */
    @Override
    public boolean hasAnyRole(String roleCodes) {
        String loginUserRoleCode = this.getLoginUserRoleCode();
        return StrUtil.split(roleCodes, Constants.COMMA).stream().anyMatch(loginUserRoleCode::contains);
    }

    /**
     * 获取当前用户的角色编码集合
     */
    private String getLoginUserRoleCode() {
        return this.getLoginUser().getRole().getRoleCode();
    }

    /**
     * 管理员类型（SUPER_ADMIN超级管理员）
     * 判断当前登录用户是否是超级管理员
     */
    @Override
    public boolean isSuperAdmin() {
        return this.isAdmin(UserTypeEnum.SUPER_ADMIN);
    }

    /**
     * 判断当前登录用户是否是指定类型的管理员
     */
    private boolean isAdmin(UserTypeEnum adminType) {
        return adminType.equals(this.getLoginUser().getUserType());
    }

    /**
     * 判断当前登录用户是否包含所有角色
     */
    @Override
    public boolean hasAllRole(String roleCodes) {
        String loginUserRoleCode = this.getLoginUserRoleCode();
        return StrUtil.split(roleCodes, Constants.COMMA).stream().allMatch(loginUserRoleCode::contains);
    }

    /**
     * 获取当前登录用户的角色id
     */
    @Override
    public Long getLoginUserRoleId() {
        return this.getLoginUser().getRole().getId();
    }

    @Override
    public LoginData getLoginUserUpToDate() {
        SystemUser sysUser = systemUserDao.queryUserById(this.getLoginUserId());
        //构造SysLoginUser
        return authService.getLoginUserUpToDate(sysUser);
    }
}
